package com.chance.cc.crawler.development.scripts.douyin.phone;

import com.alibaba.fastjson.JSON;
import com.chance.cc.crawler.meta.core.bean.crawler.CrawlerDomainKeys;
import com.chance.cc.crawler.sheduler.job.context.ScheduleHandlerContext;
import com.chance.cc.crawler.sheduler.job.handler.SchedulerHandler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.vidstige.jadb.JadbDevice;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Map;

import static com.chance.cc.crawler.sheduler.job.ScheduleJob.ScheduleKeyWordKey;
import static com.chance.cc.crawler.sheduler.job.handler.phone.AdbShellUtils.*;

/**
 * @author bx
 * @date 2020/12/4 0004 11:28
 */
public class DYPhoneSearchVideoCommentCustomMI5SADBScript extends SchedulerHandler{

    private static Logger log = LoggerFactory.getLogger(DYPhoneSearchVideoCommentCustomMI5SADBScript.class);

    @Override
    public String domain() {
        return "douyin";
    }

    @Override
    public boolean isHandle(ScheduleHandlerContext context) {
        return true;
    }

    @Override
    public void handle(ScheduleHandlerContext context) {

        //do some thing
        JadbDevice jadbDevice = context.getJadbDevice();
        Map<String, String> scheduleDataMap = context.getScheduleDataMap();
        String crawlerDomainKeysJson = scheduleDataMap.get(ScheduleKeyWordKey);
        CrawlerDomainKeys crawlerDomainKeys = JSON.parseObject(crawlerDomainKeysJson, CrawlerDomainKeys.class);
        String keyWord = crawlerDomainKeys.getKeyword();
        int swipeNumbersForVideo = Integer.valueOf(scheduleDataMap.getOrDefault("phone_swipe_numbers", "100"));
        int swipeNumbersForComment = Integer.valueOf(scheduleDataMap.getOrDefault("phone_comment_swipe_numbers", "20"));
        try {
            dyKeyWordSearch(jadbDevice,keyWord,swipeNumbersForVideo,swipeNumbersForComment,context);
        } catch (Exception e) {
            try {
                dyKeyWordSearch(jadbDevice,keyWord,swipeNumbersForVideo,swipeNumbersForComment,context);
            } catch (Exception e1) {
                log.error(e.getMessage(),e1);
            }
        }
    }

    public void dyKeyWordSearch(JadbDevice device, String keyword, int swipeNumbersForVideo,int swipeNumbersForComment,ScheduleHandlerContext context)  throws Exception {
        log.info("device {} dy kw search script--begin------------------",device.getSerial());

        //当前是否是在初始页面
        if(!initHome(device)){ //是否在通讯录页面
            throw new Exception("无法初始到home页，keyword:" + keyword);
        }

        executeShell(2500,device,"input tap 980 130"); // 搜索图标
        log.info("device {} dy kw search script--点击dy搜索图标",device.getSerial());

        //采集关键词
        dyKeywordSearch(device,keyword,swipeNumbersForVideo,swipeNumbersForComment,context);


        //返回到dy首页
        executeShell(device,"input keyevent 4");
        log.info("device {} dy kw search 返回抖音首页");
    }

    private void  dyKeywordSearch(JadbDevice device, String keyword, int swipeNumbersForVideo,int swipeNumbersForComment,ScheduleHandlerContext context) throws Exception {
        String encode = Base64.getEncoder().encodeToString(keyword.getBytes());
        executeShell(device,"adb -s "+device.getSerial()+" shell am broadcast -a ADB_INPUT_B64 --es msg "+encode,true);//文本输入
        log.info("device {} script--输入dy需要查询的关键词[{}]",device.getSerial(),keyword);

        //调出华为输入法，点击搜索按钮，再切换回adb输入法
        executeShell(4000,device,"ime set com.baidu.input_mi/.ImeService"); //小米手机
        log.info("device {} dy kw search 切换小米输入法",device.getSerial());
        executeShell(device,"input tap 980 1819");
        log.info("device {} dy kw search 点击搜索按钮",device.getSerial());
        executeShell(6000,device,"ime set com.android.adbkeyboard/.AdbIME");
        log.info("device {} dy kw search 切换adb输入法",device.getSerial());

        //设置发布时间
        String[] releaseTimeCoordinate = getCoordinate(dumpUI(device), "text", "发布时间");
        if (releaseTimeCoordinate == null || releaseTimeCoordinate.length !=2){
            throw new Exception("无法获取发布时间坐标,kw: " + keyword);
        }
        executeShell(device,"input tap "+releaseTimeCoordinate[0]+" "+releaseTimeCoordinate[1]);
//        executeShell(3000,device,"input tap 160 700");//一天内
        executeShell(3000,device,"input tap 160 870");//一周内
        log.info("device {} dy kw search 设置发布时间",device.getSerial());

        //滑动屏幕，采集视频
        String lastTimeVideoKey = null;
        ByteArrayOutputStream baos = null;
        for(int start=1;start<=swipeNumbersForVideo;start++){
//            executeShell(device,"input swipe 530 1600 550 500 200");
            baos = dumpUIForOutPutStream(device,3);

            String comments = getTextNodeVaule(new ByteArrayInputStream(baos.toByteArray()), "resource-id", "com.ss.android.ugc.aweme:id/gwv");//评论
            if (StringUtils.isNotBlank(comments) && !"评论".equals(comments)){
                String likes = getTextNodeVaule(new ByteArrayInputStream(baos.toByteArray()), "resource-id", "com.ss.android.ugc.aweme:id/gzg");//点赞
                String forwards = getTextNodeVaule(new ByteArrayInputStream(baos.toByteArray()), "resource-id", "com.ss.android.ugc.aweme:id/hcx");//转发
                String currentVideoKey = StringUtils.joinWith("-",likes,comments,forwards);
                if (StringUtils.isBlank(lastTimeVideoKey) || !lastTimeVideoKey.equals(currentVideoKey)){
                    //采集评论
                    String[] commentCoordinate = getCoordinate(new ByteArrayInputStream(baos.toByteArray()), "resource-id", "com.ss.android.ugc.aweme:id/gwv");
                    executeShell(device,"input tap "+commentCoordinate[0]+" "+commentCoordinate[1]);

                    commentCrawler(device,swipeNumbersForComment);
                    lastTimeVideoKey = currentVideoKey;
                }
            }

//            if(StringUtils.isNotBlank(lastTimeVideoKey)){ //只采集第一个有评论的视频
//                break;
//            }

            executeShell(device,"sh /data/local/tmp/swipe_events.sh");
            if (isBreak(context,baos,keyword)){
                break;
            }
        }
        IOUtils.close(baos);
        executeShell(device,"input keyevent 4");
        log.info("device {} dy kw search 返回搜索页",device.getSerial());
    }

    private void commentCrawler(JadbDevice device,int swipeNumbersForComment) throws Exception {
        ByteArrayOutputStream baos = null;

        for(int start=1;start<=swipeNumbersForComment;start++){
//            executeShell(device,"input swipe 540 1600 540 100");
            executeShell(device,"sh /data/local/tmp/swipe_events.sh");
            if(start % 10 == 0){ // 每5次查看一次
                baos = dumpUIForOutPutStream(device,3);
                if (isBreak(null,baos,null)){
                    break;
                }
            }
        }

        IOUtils.close(baos);
        executeShell(device,"input keyevent 4");
        log.info("device {} dy kw search 返回视频列表页",device.getSerial());
    }

    private boolean isBreak(ScheduleHandlerContext context,ByteArrayOutputStream baos,String keyword) throws IOException {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        String[] coordinate = getCoordinate(inputStream, "text", "搜索结果为空");
        if (coordinate != null){
            return true;
        }

        inputStream = new ByteArrayInputStream(baos.toByteArray());
        coordinate = getCoordinate(inputStream, "text", "暂时没有更多了");
        if (coordinate != null){
            return true;
        }

        inputStream = new ByteArrayInputStream(baos.toByteArray());
        coordinate = getCoordinate(inputStream, "text", "部分评论因未授权抖音，暂不支持查看");
        if (coordinate != null){
            return true;
        }

        inputStream = new ByteArrayInputStream(baos.toByteArray());
        coordinate = getCoordinate(inputStream, "text", "您今日的搜索次数已达上限");
        if (coordinate != null){
            context.setContinueCurrentSchedule(false);
            log.info("今日搜索次数已达上限，即将推出，关键词：{}",keyword);
            return true;
        }
        return false;
    }

    private boolean initHome(JadbDevice device) throws Exception {

        for(int backCOunt=0;backCOunt < 10;backCOunt++){
            ByteArrayOutputStream baos = dumpUIForOutPutStream(device,5);
            InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
            String[] homeCoordinate = getCoordinate(inputStream, "text", "首页", false);

            if (homeCoordinate != null && homeCoordinate.length == 2){
                inputStream = new ByteArrayInputStream(baos.toByteArray());
                String[] searchCoordinate = getCoordinate(inputStream,"content-desc","搜索");
                if (searchCoordinate == null){
                    executeShell(device,"input tap "+homeCoordinate[0]+" "+homeCoordinate[1]);
                }
                return true;
            }
            if (isUpdate(device,baos)){
                continue;
            }
            if (isMailList(device,baos)){
                continue;
            }
            if (isRemind(device,baos)){
                continue;
            }
            executeShell(3000,device,"input keyevent 4");
        }
        return false;
    }

    private boolean isUpdate(JadbDevice device,ByteArrayOutputStream baos) throws Exception {

        InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        String[] updateCoordinate = getCoordinate(inputStream, "text", "检测到更新", false);

        if (updateCoordinate != null && updateCoordinate.length == 2){
            inputStream = new ByteArrayInputStream(baos.toByteArray());
            String[] laterCoordinate = getCoordinate(inputStream,"text","以后再说");
            if (laterCoordinate != null){
                executeShell(device,"input tap "+laterCoordinate[0]+" "+laterCoordinate[1]);
            } else {
                log.error("抖音更新界面有变动，dump ui：{}", IOUtils.readLines(inputStream,"utf-8"));
                return false;
            }
            return true;
        }
        return false;
    }

    private boolean isMailList(JadbDevice device,ByteArrayOutputStream baos) throws Exception {

        InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        String[] updateCoordinate = getCoordinate(inputStream, "text", "发现通讯录好友", false);

        if (updateCoordinate != null && updateCoordinate.length == 2){
            inputStream = new ByteArrayInputStream(baos.toByteArray());
            String[] laterCoordinate = getCoordinate(inputStream,"text","暂时不要");
            if (laterCoordinate != null){
                executeShell(device,"input tap "+laterCoordinate[0]+" "+laterCoordinate[1]);
            } else {
                log.error("抖音通讯录界面有变动，dump ui：{}", IOUtils.readLines(inputStream,"utf-8"));
                return false;
            }
            return true;
        }
        return false;
    }

    private boolean isRemind(JadbDevice device,ByteArrayOutputStream baos) throws Exception {

        InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        String[] updateCoordinate = getCoordinate(inputStream, "text", "为呵护未成年人健康成长", false,true);

        if (updateCoordinate != null && updateCoordinate.length == 2){
            inputStream = new ByteArrayInputStream(baos.toByteArray());
            String[] laterCoordinate = getCoordinate(inputStream,"text","我知道了");
            if (laterCoordinate != null){
                executeShell(device,"input tap "+laterCoordinate[0]+" "+laterCoordinate[1]);
            } else {
                log.error("抖音提醒界面有变动，dump ui：{}", IOUtils.readLines(inputStream,"utf-8"));
                return false;
            }
            return true;
        }
        return false;
    }
}
